<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<!-- Mirrored from bos.asmhackers.net/docs/partition tables/Partitions.htm by HTTrack Website Copier/3.x [XR&CO'2013], Tue, 07 Oct 2014 11:07:01 GMT -->
<HEAD><TITLE>Partitions</TITLE>

<META content="text/html; charset=koi8-r" http-equiv=Content-Type>
<META content="Alex Verstak" name=Author>
<META content="MSHTML 5.00.2614.3500" name=GENERATOR></HEAD>
<BODY> 
<CENTER>
<H1>Partitions</H1></CENTER>
<HR width="100%">

<H2>Introduction</H2>This document concerns only hard drives. Floppy disks, 
CD-ROM, and ZIP drives are not normally split into partitions. You should 
familiarize yourself with CHS and LBA sector addressing modes before reading 
this document. 
<H2>Here we go</H2>The first sector of the hard disk must contain the 
information about disk structure. If the disk is booted from, it must also 
contain a boot loader. As you remember, this sector is at CHS <TT>(0, 0, 1)</TT> 
or LBA <TT>(0)</TT>. To verify that this sector is valid, one should read a 16 
bit word at offset <TT>1FE</TT> from the beginning of this sector and compare it 
to <TT>AA55</TT> (needless to say, the word is in Intel little endian notation). 
If this word is different from <TT>AA55</TT>, the hard disk should not be 
considered valid. The typical behavior of decent operating systems in this case 
is to silently ignore this hard disk. 
<P>The information about disk partitions starts from the predefined offset 
<TT>1BE</TT> from the beginning of the first sector. There are four partition 
table entries at this offset, each taking up 10h bytes: <BR>&nbsp; 
<TABLE border=1 width="34%">
  <TBODY>
  <TR>
    <TD><I>Partition</I></TD>
    <TD><I>Offset</I></TD></TR>
  <TR>
    <TD><TT>1</TT></TD>
    <TD><TT>1BE</TT></TD></TR>
  <TR>
    <TD><TT>2</TT></TD>
    <TD><TT>1CE</TT></TD></TR>
  <TR>
    <TD><TT>3</TT></TD>
    <TD><TT>1DE</TT></TD></TR>
  <TR>
    <TD><TT>4</TT></TD>
    <TD><TT>1FE</TT></TD></TR></TBODY></TABLE>The structure of each entry is below: 
<BR>&nbsp; 
<TABLE border=1>
  <TBODY>
  <TR>
    <TD><I>Offset in entry</I></TD>
    <TD><I>Size in bytes</I></TD>
    <TD><I>Meaning</I></TD></TR>
  <TR>
    <TD><TT>0</TT></TD>
    <TD><TT>1</TT></TD>
    <TD><TT><A href="http://averstak.tripod.com/fatdox/partition.htm#bi">Boot 
      indicator</A></TT></TD></TR>
  <TR>
    <TD><TT>1</TT></TD>
    <TD><TT>1</TT></TD>
    <TD><TT><A 
      href="http://averstak.tripod.com/fatdox/partition.htm#bh">Beginning head 
      number</A></TT></TD></TR>
  <TR>
    <TD><TT>2</TT></TD>
    <TD><TT>1</TT></TD>
    <TD><TT><A 
      href="http://averstak.tripod.com/fatdox/partition.htm#bh">Beginning sector 
      and high cylinder number</A></TT></TD></TR>
  <TR>
    <TD><TT>3</TT></TD>
    <TD><TT>1</TT></TD>
    <TD><TT><A 
      href="http://averstak.tripod.com/fatdox/partition.htm#bh">Beginning low 
      cylinder number</A></TT></TD></TR>
  <TR>
    <TD><TT>4</TT></TD>
    <TD><TT>1</TT></TD>
    <TD><TT><A 
      href="http://averstak.tripod.com/fatdox/partition.htm#si">System 
      indicator</A></TT></TD></TR>
  <TR>
    <TD><TT>5</TT></TD>
    <TD><TT>1</TT></TD>
    <TD><TT><A 
      href="http://averstak.tripod.com/fatdox/partition.htm#bh">Ending head 
      number</A></TT></TD></TR>
  <TR>
    <TD><TT>6</TT></TD>
    <TD><TT>1</TT></TD>
    <TD><TT><A 
      href="http://averstak.tripod.com/fatdox/partition.htm#bh">Ending sector 
      and high cylinder number</A></TT></TD></TR>
  <TR>
    <TD><TT>7</TT></TD>
    <TD><TT>1</TT></TD>
    <TD><TT><A 
      href="http://averstak.tripod.com/fatdox/partition.htm#bh">Ending low 
      cylinder number</A></TT></TD></TR>
  <TR>
    <TD><TT>8</TT></TD>
    <TD><TT>4</TT></TD>
    <TD><TT><A 
      href="http://averstak.tripod.com/fatdox/partition.htm#ns">Number of 
      sectors preceding the partition</A></TT></TD></TR>
  <TR>
    <TD><TT>C</TT></TD>
    <TD><TT>4</TT></TD>
    <TD><TT><A 
      href="http://averstak.tripod.com/fatdox/partition.htm#ns">Number of 
      sectors in the partition</A></TT></TD></TR></TBODY></TABLE><TT>&nbsp;</TT> 
<BR>Let us take a closer look at each field and its meaning. 
<P><A name=bi></A><I>Boot indicator</I> is <TT>80h</TT> for bootable partitions 
and <TT>zero</TT> for other valid partitions. If it is neither <TT>80h</TT> nor 
<TT>zero</TT>, the corresponding partition should be considered invalid. Invalid 
partitions are silently ignored by most of the systems. For the disk to be 
bootable, exactly one entry must contain <TT>80h</TT> in this field. However, 
the condition when more than one entry is marked as bootable should not be 
considered fatal error. If two or more of the partitions are bootable, all 
should be treated as valid partitions. 
<P><A name=bh></A><I>Beginning cylinder, head, and sector numbers</I> point to 
the first sector of the partition in CHS notation. Two high bits of 
"<TT>beginning sector and high cylinder number</TT>" are two high bits of 
cylinder number. Similarly, <I>ending cylinder, head, and sector</I> point to 
the last sector in the partition. They are in exactly the same format. 
<P><TT>Sector="sector and high cylinder number" and 4F</TT> 
<BR><TT>Cylinder="low cylinder number"+(("sector and high cylinder number" shr 
6) shl 8)</TT> 
<P>Thus, BIOS imposes the following limitations: <BR>&nbsp; 
<TABLE border=1>
  <TBODY>
  <TR>
    <TD><I>CHS</I></TD>
    <TD><I>Minimum value</I></TD>
    <TD><I>Maximum value</I></TD>
    <TD><I>Number of bits</I></TD>
    <TD><I>Number of values</I></TD></TR>
  <TR>
    <TD><I>Sector</I></TD>
    <TD><TT>1</TT></TD>
    <TD><TT>64</TT></TD>
    <TD><TT>6</TT></TD>
    <TD><TT>64</TT></TD></TR>
  <TR>
    <TD><I>Head</I></TD>
    <TD><TT>0</TT></TD>
    <TD><TT>255</TT></TD>
    <TD><TT>8</TT></TD>
    <TD><TT>256</TT></TD></TR>
  <TR>
    <TD><I>Cylinder</I></TD>
    <TD><TT>0</TT></TD>
    <TD><TT>1023</TT></TD>
    <TD><TT>10</TT></TD>
    <TD><TT>1024</TT></TD></TR></TBODY></TABLE>If you multiply the values in the 
last column out and multiply the result by sector size, you will get the hard 
disk size limitation of 8 GB. If you consider that older IDE implementations 
supported up to 16 heads, you will get the infamous 512 MB barrier. How this 
barrier is dealt with was described in previous documents. 
<P>If disk was partitioned in LARGE or LBA modes, CHS addresses in these fields 
are logical CHS addresses. Therefore, you should better use BIOS services to 
access CHS partitions. But since BIOS is terribly inefficient, you may take a 
risk of providing the same software CHS translation as it does. To do it, get 
physical device parameters from the device and logical device parameters from 
BIOS. If any of them equals to zero, the disk is misconfigured and should not be 
used. Then compare physical <TT>SectorsPerHead</TT> against logical 
<TT>SectorsPerHead</TT>. If they are not equal, BIOS is using some strange CHS 
translation mode, and you should use BIOS services to access the partition. If 
they are equal, divide physical <TT>NumberOfCylinders</TT> by logical 
<TT>NumberOfCylinders</TT> and remember the result. Then divide logical 
<TT>HeadsPerCylinder</TT> by physical <TT>HeadsPerCylinder</TT>. If the quotient 
is not the same as the result of the previous division, or if the quotient is 
not the power of two, you should use BIOS services for accessing the partition. 
Otherwise use this quotient to provide BIOS-like CHS translation. 
<P>Certainly, sanity check on these CHS values is absolutely necessary. Systems 
vary in the ways how they handle this stage. I recommend the following simple 
algorithm. I insist that you copy partition table to the temporary buffer with 
easier to handle format. Zero-extend <TT>Cylinder</TT>, <TT>Head</TT>, and 
<TT>Sector</TT> values to 16 bit words and use signed arithmetic. First of all, 
make sure that none of the partitions starts at CHS <TT>(0, 0, 1)</TT>. Remove 
all that do. Then make sure that none of the partitions overlap. If any two 
partitions do overlap, my best guess would be truncating the preceding partition 
so that they don't overlap any more. Do this by setting ending sector address of 
the preceding partition to the beginning sector address of the next partition 
minus one. Do not forget that arithmetic operations on CHS addresses have 
peculiarities. After that check that none of the ending sector addresses exceeds 
physical disk size. Truncate ending sector addresses, if necessary, by setting 
them to CHS <TT>(NumberOfCylinders-1, HeadsPerCylinder-1, SectorsPerHead)</TT>. 
Finally, make sure that each partition has at least one sector in it. If 
beginning sector address is greater than or equal to ending sector address, such 
partition should be considered invalid. By now you should have valid partition 
information in your temporary buffer. Use this information to access partitions. 
But unless you are a disk analyzer program, do not write any changes to the 
partition table itself. 
<P>Now I would like to say a couple of words about compatibility. Many programs 
expect that the very first partition starts at CHS <TT>(0, 1, 1)</TT> and that 
all partitions except the first one start at even cylinder boundaries, CHS 
<TT>(2*k, 0, 1)</TT>. They also expect that partitions cover the disk completely 
and are consecutive on the disk. If you are paranoid, also make sure that the 
very first partition is bootable. 
<P><A name=ns></A><I>Number of sectors preceding the partition</I> is its LBA 
address. <I>Number of sectors in the partition</I> is its LBA length. Note that 
these values are essentially duplicating the CHS values that are described 
above. They must define exactly the same partition as CHS values. When LBA and 
CHS values are in conflict, some heuristics is necessary. Check system indicator 
to find out which values should be used. Give precedence to LBA values in LBA 
partitions and to CHS values in CHS partitions. Do not make any assumptions 
about the partitions you don't know. You should not access them anyway. 
<P>The same sanity check should be performed on LBA values, as was on CHS 
values. Remove the partitions that start at LBA <TT>(0)</TT>. If any two 
partitions overlap, truncate the preceding partition. Make sure that none of the 
sums of partition address and size exceeds disk capacity and truncate partition 
size if necessary. Remove partitions that have zero size. 
<P>Note that sanity check across CHS and LBA partitions would be very nice. If 
CHS and LBA addresses are consistent for each partition, it is easier to perform 
this check by converting all addresses to LBA, doing the check, and then 
converting the results back to CHS. Unfortunately, if CHS and LBA addresses of 
any partition are in conflict, sanity check can do more harm than good because 
of different CHS translation modes. My recommendation in this case is to do 
separate sanity checks between CHS partitions and LBA partitions, but not across 
them. 
<P><A name=si></A>Some of the <I>system indicators</I> are in the table below: 
<BR>&nbsp; 
<TABLE border=1>
  <TBODY>
  <TR>
    <TD><I>Value</I></TD>
    <TD><I>System</I></TD>
    <TD><I>Capacity</I></TD>
    <TD><I>Translation mode</I></TD></TR>
  <TR>
    <TD><TT>00</TT></TD>
    <TD><TT>Unknown</TT></TD>
    <TD></TD>
    <TD></TD></TR>
  <TR>
    <TD><TT>01</TT></TD>
    <TD><TT>DOS FAT12, 16 bit sector number</TT></TD>
    <TD><TT>&lt;10MB</TT></TD>
    <TD><TT>CHS</TT></TD></TR>
  <TR>
    <TD><TT>02</TT></TD>
    <TD><TT>XENIX</TT></TD>
    <TD></TD>
    <TD></TD></TR>
  <TR>
    <TD><TT>04</TT></TD>
    <TD><TT>DOS FAT16, 16 bit sector number</TT></TD>
    <TD><TT>&lt;32MB</TT></TD>
    <TD><TT>CHS</TT></TD></TR>
  <TR>
    <TD><TT>05</TT></TD>
    <TD><TT>DOS Extended partition</TT></TD>
    <TD></TD>
    <TD><TT>CHS</TT></TD></TR>
  <TR>
    <TD><TT>06</TT></TD>
    <TD><TT>DOS 4.0 FAT16, 32 bit sector number</TT></TD>
    <TD><TT>&gt;=32MB</TT></TD>
    <TD><TT>CHS</TT></TD></TR>
  <TR>
    <TD><TT>0B</TT></TD>
    <TD><TT>DOS FAT32</TT></TD>
    <TD><TT>&lt;2TB</TT></TD>
    <TD><TT>CHS</TT></TD></TR>
  <TR>
    <TD><TT>0C</TT></TD>
    <TD><TT>DOS FAT32</TT></TD>
    <TD><TT>&lt;2TB</TT></TD>
    <TD><TT>LBA</TT></TD></TR>
  <TR>
    <TD><TT>0E</TT></TD>
    <TD><TT>DOS FAT16, 32 bit sector number</TT></TD>
    <TD><TT>&gt;=32MB</TT></TD>
    <TD><TT>LBA</TT></TD></TR>
  <TR>
    <TD><TT>0F</TT></TD>
    <TD><TT>DOS Extended partition</TT></TD>
    <TD></TD>
    <TD><TT>LBA</TT></TD></TR>
  <TR>
    <TD><TT>51h</TT></TD>
    <TD><TT>Ontrack extended partition</TT></TD>
    <TD></TD>
    <TD></TD></TR>
  <TR>
    <TD><TT>64h</TT></TD>
    <TD><TT>Novell</TT></TD>
    <TD></TD>
    <TD></TD></TR></TBODY></TABLE><TT>&nbsp;</TT> <BR>Note that 2 TB limit for 
partition type <TT>0C</TT> is not in contradiction with BIOS 8 GB limitation 
because LBA addressing is used. However, I don't know where the 2 TB limit for 
partition type <TT>0B</TT> comes from. Well, it comes from one of the documents 
in the Microsoft Knowledge Base, but I fail to see how the CHS partition larger 
than 8 GB can be implemented. 
<P>This table does not mean to be exhaustive. New operating systems and 
utilities appear and die here and there, so this table will always be 
incomplete. Common sense says that when you find an unfamiliar value in the 
table, you should not attempt to modify any of the sectors in this partition. 
The best policy is to silently ignore such partition. 
<H2>DOS Extended Partitions</H2>Two of the system indicators deserve special 
attention. They are extended DOS partitions <TT>05</TT> and <TT>0F</TT>. 
Extended DOS partition contains a secondary partition table and some space for 
nested partitions. The secondary partition table is right at the beginning 
sector of the DOS extended partition. Its format is almost the same as that of 
the main partition table described above. However, some things must be taken 
into consideration. 
<P>Extended partition must have one or two entries. I do not encourage you to 
handle the situation when extended partition has more than two entries because 
this partition is very DOS specific and unlikely to be changed. I think, it is 
safe to check only the first two entries of the extended partition. 
<P>One of the entries should define a DOS partition. For this entry, CHS and LBA 
addresses are relative to the sector containing the secondary partition table. 
Another entry may define the deeper nested extended DOS partition. In this case, 
CHS and LBA addresses are relative to the beginning of the physical disk. This 
also implies that there can be many nested extended partitions, so the function 
that looks through them should keep track of used resources and handle the 
situation when it runs out of buffers. All nested partitions must fall within 
the mother extended partition. Truncate them if they don't. None of the 
partitions can be bootable, but this should be taken into consideration only by 
special disk analyzing programs. 
<P>Finally, primary partition may have multiple extended partition entries. 
<H2>Other DOS Notes</H2>The information below is specific to DOS operating 
system. 
<P>Everything that is not DOS extended partition is called primary partition. 
For the unclear reasons DOS manuals say that every partition table should 
contain only one primary partition. But DOS does support multiple primary 
partitions correctly, and you should too. 
<P>Letters for DOS disks are assigned in the following order. Letters 'A' and 
'B' are assigned to floppy drives. If there is one floppy drive, it is assigned 
'A'. The letter 'C ' is assigned to the first primary partition on the first 
hard drive. The next letters are assigned to first primary partitions on all 
hard drives. Then go volumes inside the extended partitions on all hard drives, 
in the order they appear. First, all extended partitions on the first drive are 
given letters, then - on the second drive, etc. Then the remaining primary 
partitions on all drives are assigned letters. Finally, CD-ROM drives take their 
share of letters. Note that the letters that CD-ROM drives have can be 
configured by software. 
<P>
<HR width="100%">
<BR>Author:&nbsp; <A href="mailto:averstak@erols.com">Alex Verstak</A>&nbsp; 
3/10/1998 <BR>&nbsp; </BODY>
<!-- Mirrored from bos.asmhackers.net/docs/partition tables/Partitions.htm by HTTrack Website Copier/3.x [XR&CO'2013], Tue, 07 Oct 2014 11:07:01 GMT -->
</HTML>

